package anatex.kea.genex.extractor;

import java.util.*;
import java.util.regex.*;

import anatex.domain.CustomLocale;
import anatex.domain.Stopword;
import anatex.kea.KeywordExtractorAlgoException;

public class StemPhraseSuffix {

	CustomLocale loc = null;
	protected String text;
	protected POSDetection pd;
	protected Parameters parameters;
	ArrayList<String> stopWords = null;
	
	public StemPhraseSuffix(String t, Parameters p) throws KeywordExtractorAlgoException {
		text = t;
		parameters = p;
		pd = new POSDetection();
	}
	
	protected ArrayList<String> getStopWords() {
		if (null == stopWords) {
			stopWords = new ArrayList<String>();
			
			//TODO must get locale from doc
			List<Stopword> s = Stopword.findStopwordsByCustomLocale(loc).getResultList();
			Iterator<Stopword> sit = s.iterator();
			
			while (sit.hasNext()) {
				stopWords.add(sit.next().getWord());
			}
		}
		
		return stopWords;
	}
	
	public void setCustomLocale (CustomLocale l) {
		loc = l;
	}
	
	public void setText(String t) {
		text = t;
	}
	
	public void setParameters(Parameters p) {
		parameters = p;
	}
	
	public String getBestSuffix(String stemPhrase) {
		
		String suffix = "";
		HashMap<String, Integer> candidates = new HashMap<String, Integer>();
		int score = -1;
		Integer suppressProper = (Integer)parameters.get(Parameters.SUPPRESS_PROPER);
		getStopWords();
		
		Pattern p = Pattern.compile("\\b" + stemPhrase.trim().replaceAll("\\s", "([^\\\\s]+)?[\\\\s]*") + "([^\\s]+)?\\b", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
		Matcher m = p.matcher(text);
		
//		System.out.println("Working with " + stemPhrase + " and pattern " + p.toString());
		
		//count occurrences
		while (m.find()) {
			String match = m.group(0);
			
			if (candidates.containsKey(m)) {
				candidates.put(match, candidates.get(match) + 1);
			} else {
				candidates.put(match, 1);
			}
		}
		
		//remove suffixes with unwanted pos
		ArrayList<Object[]> pos = new ArrayList<Object[]>();
		HashMap<String, ArrayList<Object[]>> capitalizations;
		capitalizations = new HashMap<String, ArrayList<Object[]>>();
		
		for (String s : candidates.keySet()) {
//			System.out.println("Getting pos for " + s);
			
			int wordIndex = 0;
			int nounCount = 0;
			int capitalsCount = 0;
			
			//check for stopwords
			String[] words = s.split("\\s");
			boolean hasStopWord = false;
			for (String w : words) {
				if (stopWords.contains(s)) {
					hasStopWord = true;
					
					break;
				}
			}
			
			if (hasStopWord) {
				continue;
			}
			
			pos = pd.getTags(Arrays.asList(words));
			ListIterator<Object[]> lit = pos.listIterator();
			
			while(lit.hasNext()) {
				Object[] ps = lit.next();
				
				wordIndex ++;
				
				String part = (String)ps[0];
				
				//estimate capitalization status
				if (Character.isUpperCase(part.charAt(0))) {
					capitalsCount ++;
				}
				
				char pc = part.charAt(0);
				if ('V' == pc) {
//					System.out.println(ps[0] + " is a verb and weight will be set to 0");
					
					candidates.put(s, 0);
				} else if ('J' == pc && pos.size() == wordIndex) {
//					System.out.println(ps[0] + " is an adjective ending and weight will be set to 0");
					
					candidates.put(s, 0);
				} else {
					if ('N' == pc) {
						nounCount ++;
					}
					
//					System.out.println(ps[0] + " is " + ps[1]);
					
					if (score < (Integer)candidates.get(s) || 
							(pos.size() == 1 && s.toLowerCase() == suffix && !Character.isUpperCase(suffix.charAt(0))) //get best capitalization for one-word phrase
							) {
						suffix = s;
						
						score = candidates.get(s);
					}
				}
				
				if (! lit.hasNext()) {
//					System.out.println("\tCapitalization is: " + s);
					if (! capitalizations.containsKey(s.toLowerCase())) {
						capitalizations.put(s.toLowerCase(), new ArrayList<Object[]>());
					}
					
					capitalizations.get(s.toLowerCase()).add(new Object[] {s, wordIndex, nounCount, capitalsCount});
				}
			}
		}
		
		if ("" == suffix) {
			return "";
		}
		
		//TODO implement full step 9 form the Extractor - check not only the first leter for capitalization
		//analyze and pick best capitalization
		int bestCapitalization = 0; //0 - inconsistent; 1 - all lower; 2 - all upper
		ListIterator<Object[]> lit = capitalizations.get(suffix.toLowerCase()).listIterator();
		
		while (lit.hasNext()) {
			Object[] item = lit.next();
			
			//if only one word and capitals
			if (1 == (Integer)item[1] && 0 == (Integer)item[3]) {
				suffix = (String)item[0];
				
				break;
			} else {
				if (0 == (Integer)item[3] && 2 != bestCapitalization) {
					suffix = (String)item[0];
					
					bestCapitalization = 1;
				} else if ((Integer)item[1] == (Integer)item[3] && (Integer)item[1] != (Integer)item[2] && 1 != bestCapitalization) {
					suffix = (String)item[0];
					
					bestCapitalization = 2;
				}
			}
			
			if (! lit.hasNext() && 0 == bestCapitalization) {
				suffix = (String)item[0];
			}
		}
		
		//do not use proper noun if configured so
		if (1 == suppressProper && 2 == bestCapitalization) {
			suffix = "";
		}
		
		return suffix;
	}
	
}
